home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 43
/
Aminet 43 (2001)(GTI - Schatztruhe)[!][Jun 2001].iso
/
Aminet
/
text
/
edit
/
BareED.lha
/
BareED
/
DAC
/
source
/
Dump.c
< prev
next >
Wrap
C/C++ Source or Header
|
2001-03-21
|
32KB
|
946 lines
/*
Copyright March 2001 J.v.d.Loo
Treat this source code and the load file based on this source as Freeware - I would say Public
Domain when this wouldn't give other people the right to add their copyright signs - which among
other things can mean that the files Dump and Dump.c cannot be used freely...
Start over:
This file is not meant as lesson how to use the "printer device" but as an example how to use
the (poor) DAC interface of BareED.
Note: Any DAC-application will be started from BareED!
A DAC-application will get a normal Workbench-start-up-message with additional
information and functions that it may use.
A DAC-aaplication may be written as base-relative (small code/data) or as large
code/data model - it doesn't matter. The base register A4 of your program is remembered
and restored by BareED!
-> NOTE: Traditionally register A5 is used by the E-compiler - but currently BareED does
not care about it - sorry.
If a CallBack-Hook function of a DAC-application is called back you have to restore on
exit all registers to their initial state, except D0-D1, A0-A1, A4.
Note well: BareED is locked, better said: protected against modifications from the
outside (non-DAC-applications), which means that the archive cannot be gone
or changed when there is still at least one DAC-application alive -
exception: a marked block!!! But the addresses of BlockStart and BlockEnd
are still valid although the user could have already dismarked this block!
Additional note:
I have used standard Bitplanes and Bitmaps in this example although a 3rd
party graphic board software could be running and therewith non-standard
Bitplanes and Bitmaps (when used) would be more effective. But this requires
on OS 3.0 and 3.1 a patched "printer.device". As far as I know the OSs 3.5
and 3.9 support non-standard Bitmaps native.
Used printer by author:
Since I found no "printer driver" for my Canon BJC 2000 printer, I've freed
from dust my old Epson LQ 400 printer and used it. Because the EpsonQ driver
does not compute page sizes correctly (2804 dots in horizontal and 0 dots in
vertical direction) I wrote a new "printer driver" called EpsonLQ that fixes
these and other bugs (now it supports also the Euro-sign). Since the Epson
LQ 400 printer has only 180 dpi in vertical direction, the result of Dump is
poor. Perhaps with a better printer (device ?) the result of Dump is better.
Help needed:
If you know how to apply "anti-alias" to a given font (or how to render a
font so that a "anti-alias" text can be performed) give me a hint. If you
already managed to complete a useable routine please send it to me for free
(email M.Berson in this case: BersonM@aol.com).
*/
#include <exec/memory.h>
#include <exec/libraries.h>
#include <exec/ports.h>
#include <dos/dos.h>
#include <intuition/intuition.h>
#include <intuition/screens.h>
#include <intuition/preferences.h>
#include <graphics/gfxbase.h>
#include <graphics/gfx.h>
#include <graphics/displayinfo.h>
#include <graphics/rastport.h>
#include <graphics/text.h>
#include <libraries/locale.h>
#include <workbench/startup.h>
#include <devices/printer.h>
#include <devices/prtbase.h>
#include <devices/printer.h>
#include <devices/prtbase.h>
#include <clib/exec_protos.h>
#include <clib/graphics_protos.h>
#include <clib/intuition_protos.h>
#include <clib/locale_protos.h>
#include <clib/alib_protos.h>
#include <clib/alib_stdio_protos.h>
#if !defined(__MAXON__) && !defined(__STORM__)
#include <proto/exec.h>
#include <proto/graphics.h>
#include <proto/intuition.h>
#include <proto/gadtools.h>
#include <proto/locale.h>
#else
#include <pragma/exec_lib.h>
#include <pragma/graphics_lib.h>
#include <pragma/intuition_lib.h>
#include <pragma/gadtools_lib.h>
#include <pragma/locale_lib.h>
#endif
#include <string.h>
#if defined(__MAXON__) /* ... enable Workbench start */
struct WBStartup *WBenchMsg = NULL; /* Variable */
extern "C" void wbparse( struct WBStartup *); /* Prototype */
extern "C" void wbmain( struct WBStartup *ws) /* This is called if we're running from WB */
{
WBenchMsg = ws; /* Remember message */
wbparse( ws); /* Parse WBench arguments (argv[0....])*/
}
#endif
/* Macro by G. Nikl */
#if defined(__GNUC__)
#define ASM
#define REG(reg,arg) arg __asm(#reg)
#else
#if !defined(__MAXON__)
#define ASM __asm
#else
#define ASM
#define __saveds
#endif
#define REG(reg,arg) register __##reg arg
#endif
unsigned char VerStr[] = "$VER: DAC_Dump 21.9 (21-Mar-01)";
union PrinterIO
{
struct IOStdReq IoStd;
struct IODRPReq IoDpRP;
struct IOPrtCmdReq IoPrtCom;
};
/* Possible printer.device and I/O errors */
STRPTR ErrorText[] =
{
"\000\x0ANo error",
"\000\x0BPrinting-progress aborted",
"\000\x0CNot a graphic printer",
"\000\x0DHAM image cannot be converted", /* Cannot occur */
"\000\x0EToo large region to dump",
"\000\x0FOut of supported dimension", /* Cannot occur */
"\000\x10Not enough memory",
"\000\x11Not enough memory for print-buffer",
"\000\x12IO: Open device failed",
"\000\x13IO: Printing-progress aborted",
"\000\x14IO: Unsupported command",
"\000\x15IO: Command length did not match"
};
struct PseudoMsg
{
struct WBStartup pm_Startup; /* Only readable! */
BPTR pm_Lock; /* Hands off! */
unsigned char *pm_Name; /* Hands off! */
unsigned char pm_FileName[108]; /* Hands off! */
unsigned char pm_Dir[256]; /* Hands off! */
struct GfxBase *pm_GfxBase; /* At least v33 */
struct IntuitionBase *pm_IntuitionBase; /* At least v36 */
struct Library *pm_GadToolsBase; /* At least v36 */
struct Library *pm_DiskfontBase; /* At least v33 */
struct Library *pm_AslBase; /* At least v38 */
struct Library *pm_IconBase; /* At least v33 */
struct Library *pm_LocaleBase; /* At least v1 */
struct Library *pm_WorkbenchBase; /* At least v36 */
void *VisualInfo; /* Never release it! */
struct DrawInfo *DrawInfo; /* Never release it! */
unsigned char *pm_RegionStart;
unsigned int pm_RegionSize;
unsigned char *pm_TextStart;
unsigned char *pm_TextEnd;
unsigned char *pm_BlockStart;
unsigned char *pm_BlockEnd;
struct TextAttr *pm_FontAttr;
struct TextFont *pm_Font;
struct Window *pm_EdWindow;
unsigned int pm_TabWidth; /* In pixels */
unsigned int pm_TabStops; /* A tap stop occurs every 'n' */
unsigned int pm_RightMargin;
unsigned char *pm_CharSpace; /* Pointer to the character-spaces of the used font */
void (*pm_GetAttr)( struct TagItem *taglist); /* Currently NULL (out of order!) */
void (*pm_ChangeAttr)( struct TagItem *taglist); /* Currently NULL (out of order!) */
void (*pm_BlockInput)( void);
void (*pm_AllowInput)( void);
void (*pm_Tell)( STRPTR str);
unsigned int (*pm_CaseTell)( STRPTR str);
unsigned int (*pm_RequestNumber)( unsigned int initial, STRPTR winname, STRPTR hailtext,\
STRPTR gadtext, BOOL zero);
unsigned int (*pm_StrPixelLen)( unsigned char *start, unsigned char *end);
void (*pm_DumpStrLine)( unsigned char *start, unsigned char *end, struct RastPort *rp,\
unsigned int x, unsigned int y);
unsigned int (*pm_WidestStrLen)( unsigned char *text, unsigned char *stop,\
unsigned int (*inform_code)( unsigned int len, unsigned int line),\
unsigned int inform);
void (*pm_DumpStrings)( struct RastPort *rp,\
unsigned int (*dump_code)( unsigned int len, unsigned int line),\
unsigned char *text, unsigned char *stop);
void (*pm_FreeProgressBar)( struct ProgressBar *pb);
struct ProgressBar *(*pm_CreateProgressBar)( STRPTR wintitle, STRPTR hail, STRPTR stop, STRPTR cont, STRPTR cancel);
unsigned int (*pm_PullPBarEvent)( struct ProgressBar *pb);
void (*pm_ChangePBarIndicator)( struct ProgressBar *pb, unsigned int percent, STRPTR hail);
/* Following does not yet work properly - so don't use! */
void (*pm_TogglePBarGad)( struct ProgressBar *pb);
};
struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
struct Library *LocaleBase;
struct Library *GadToolsBase;
struct Catalog *Cat;
struct MsgPort *PrinterPort;
union PrinterIO *PIO;
struct PrinterData *PD;
struct PrinterExtendedData *PED;
struct PseudoMsg *PsMsg; /* Message got from BareED */
struct ProgressBar /* Don't use other items than this one of the ProgressBar... */
{
struct Window *pb_Window;
}; /* Don't rely on this end... */
struct ProgressBar *PB; /* Will be created */
struct RastPort *FakeRP;
struct BitMap *FakeBM;
struct ColorMap *CM;
/* Since "printer device" destroys them, I have to remember them! */
unsigned int DestHDots, DestVDots, ModeID;
unsigned int VDotsPage, VDotsLine, HDotsLine, Lines;
/* Want to show user how much alredy worked out... */
unsigned int Lines2Dump; /* Amount total lines in printout */
#define TEXTBUFFERSIZE 256 /* Storage size (buffer) for strings */
STRPTR TextBuffer;
BOOL Continue = TRUE; /* While Continue is TRUE we continue - when FALSE, we quit */
/* Offset on paper and keep track of actual line dumped */
unsigned CurrYdot, CurrLine;
/* ---------------------------------------------------------------------
I don't want to waste memory so I use an own made sprintf() function
which is much shorter (it doesn't support floats and word descriptions)
than the original!
*/
void funny_code( REG(a3, volatile char *buf), REG(d0, volatile char c) )
{
*buf++ = c; /* move.b d0,(a3)+ */
} /* rts */
#define FUNC (void (*)()) &funny_code /* Code should use: lea funny_code(An),a2 */
void SPrintf( char *buf, char *descr, ...)
{
char *args;
(char *) args = (char *) &descr; /* Address format string on stack */
args += 4; /* Address 1st additional argument */
RawDoFmt( descr, args, FUNC, buf);
}
/* -----------------------
Multilingual stuff...
NOTE: I prepared the strings so that they contain a leading word, which is set up as follow:
1st byte (an octal number)
2nd byte (an octal or hexadecimal number)
3rd byte - string start
The first two bytes (= one word) will be converted by GStr() to a longword - used as index
in the catalogue.
By the way: Several compilers have got problems with characters entered behind a backslash
(when it is also a valid format descriptor, e.g. »E« !) - so watch out!
*/
void OpenTheCatalog()
{
Cat = (struct Catalog *) OpenCatalogA( 0, "dac_dump.catalog", 0);
}
void CloseTheCatalog()
{
if (Cat)
CloseCatalog( Cat);
}
char * GStr( char *str)
{
ULONG no;
char *rstr;
no = 0;
no = ( (UBYTE) str[0] << 8) + (UBYTE) str[1]; /* Convert the two leading bytes of string into longword */
rstr = &str[2]; /* String's start */
if (Cat)
rstr = (char *) GetCatalogStr( Cat, no, rstr); /* Get string or the default... */
return rstr;
}
/* ---------------------------------
CallBack Hook for WidestStrLen()
No need here to save / load base register! - already done!
Inform user if a line exeeds the computed limit. Routine
called from the inside of WidestStrLen() !
*/
unsigned int InformCode( unsigned int len, unsigned int line)
{
unsigned int limit;
limit = PsMsg->pm_RightMargin * PsMsg->pm_CharSpace[ (UBYTE) 32];
SPrintf( TextBuffer, GStr( "\001\001Line %ld exceeds with %ld pixels limit of %ld pixels!\n\n"\
"Continue anyhow?"), line, len, limit);
Continue = PsMsg->pm_CaseTell( TextBuffer);
return Continue;
}
/* --------------------------------
CallBack Hook for DumpStrings()
No need here to save / load base register! - already done!
This routine is called from DumpStrings() - when DumpStrings()
has layed out a new line - thus we can here dump the Raster Port
contents to the printer. Meanwhile we check for user actions -
like pause, continue or abandon the printout.
*/
unsigned int DumpCode( unsigned int len, unsigned int line)
{
BOOL cont = TRUE;
unsigned int signal, sigPrt, sigWd, id, spec, flag, percent, loop;
int i;
/* Check if the dump will need a new page */
if ( VDotsPage < CurrYdot + VDotsLine) /* Fits this line onto paper? */
{
/* Remember both - to set them later on! */
spec = PIO->IoDpRP.io_Special;
flag = PIO->IoDpRP.io_Flags;
PIO->IoStd.io_Flags = IOF_QUICK; /* Need no reply from "printer.device" */
PIO->IoStd.io_Command = CMD_WRITE;
PIO->IoStd.io_Length = 1;
PIO->IoStd.io_Data = "\014"; /* Eject page (12 = FormFeed) */
WaitIO( (struct IORequest *) PIO); /* Wait until line has been dumped */
if ( DoIO( (struct IORequest *) PIO))
cont = PsMsg->pm_CaseTell( GStr( "\000\x16\Error occurred while ejecting the page!\n\n"\
"Continue anyway?") );
/* Re-do for graphic dump */
PIO->IoDpRP.io_Command = PRD_DUMPRPORT;
PIO->IoDpRP.io_Flags = flag;
PIO->IoDpRP.io_RastPort = FakeRP;
PIO->IoDpRP.io_ColorMap = CM;
PIO->IoDpRP.io_Modes = ModeID;
PIO->IoDpRP.io_SrcX = 0;
PIO->IoDpRP.io_SrcY = 0;
PIO->IoDpRP.io_SrcWidth = PsMsg->pm_RightMargin * PsMsg->pm_CharSpace[ (UBYTE) 32];
PIO->IoDpRP.io_SrcHeight = PsMsg->pm_Font->tf_YSize + 1;
PIO->IoDpRP.io_Special = spec;
PIO->IoDpRP.io_DestCols = DestHDots;
PIO->IoDpRP.io_DestRows = DestVDots;
CurrYdot = 0; /* Set to top of page */
}
if (cont == TRUE)
{
/* Send to printer... */
WaitIO( (struct IORequest *) PIO); /* Wait for last action to be completed */
SendIO( (struct IORequest *) PIO); /* Attempt to dump Raster Port */
CurrYdot += VDotsLine; /* Next offset (plus full line) */
CurrLine ++; /* One more line dumped */
/* In case the progress-bar is accessible... */
if (PB)
{
percent = CurrLine * 100 / Lines2Dump; /* How much in percent already worked out? */
SPrintf( TextBuffer, GStr( "\000\x46Printout completed to %ld%% "), percent);
PsMsg->pm_ChangePBarIndicator( PB, percent, TextBuffer);
}
/* The following construct emulates the WaitIO() function but gives us
also the chance to set and wait for other, non "printer device" related
things, here break signal (CTRL-C) and progress-bar message
*/
sigPrt = 1 << PrinterPort->mp_SigBit; /* Signal-bitmask of printer */
if (PB)
sigWd = 1 << PB->pb_Window->UserPort->mp_SigBit; /* and ditto for progress-bar */
else
sigWd = 0;
signal = Wait( SIGBREAKF_CTRL_C | sigPrt | sigWd ); /* Cheap sleep! */
/* Break signal from the outside (system monitor) ? */
if ( (signal & SIGBREAKF_CTRL_C) )
{
AbortIO( (struct IORequest *) PIO);
WaitIO( (struct IORequest *) PIO); /* Convention */
PsMsg->pm_Tell( GStr ("\000\x17Printing abandoned by user!") );
cont = FALSE;
}
/* Message from "printer device" ? */
if (cont == TRUE)
{
if ( (signal & sigPrt) )
while ( GetMsg( PrinterPort)); /* Remove only the message */
/* Check for error */
if (PIO->IoDpRP.io_Error)
{
i = PIO->IoDpRP.io_Error;
if (i < 0) /* IO error ? */
i = i * -1 + 7; /* Map to offset in table */
SPrintf( TextBuffer, GStr( "\000\x18\Error: %s"), GStr( ErrorText[i]) );
PsMsg->pm_Tell( TextBuffer);
cont = FALSE;
}
}
/* Progress-bar message? */
if (cont == TRUE)
{
if ( (signal & sigWd) )
{
id = PsMsg->pm_PullPBarEvent( PB); /* Get id of gadget clicked */
/* Pause? */
if (id == 2)
{
spec = PIO->IoDpRP.io_Special; /* Remember current state */
flag = PIO->IoDpRP.io_Flags;
WaitIO( (struct IORequest *) PIO); /* Wait for dump in progress to be completed */
PIO->IoStd.io_Flags = IOF_QUICK; /* Need no reply */
PIO->IoStd.io_Command = CMD_STOP; /* Stop dump (already completed but necessary) */
DoIO( (struct IORequest *) PIO); /* Do it now! */
loop = TRUE;
while (loop)
{
signal = Wait( SIGBREAKF_CTRL_C | sigPrt | sigWd);
/* A break signal from the outside? */
if (signal & SIGBREAKF_CTRL_C)
{
AbortIO( (struct IORequest *) PIO);
WaitIO( (struct IORequest *) PIO); /* Convention */
PsMsg->pm_Tell( GStr ("\000\x17Printing abandoned by user!") );
cont = FALSE;
loop = FALSE;
}
if (cont && loop)
{
/* Message from device? - can only be "stopped"! */
if ( (signal & sigPrt) )
while ( GetMsg( PrinterPort)); /* Remove only the message */
/* Check for error */
if (PIO->IoDpRP.io_Error)
{
i = PIO->IoDpRP.io_Error;
if (i < 0) /* IO error ? */
i = i * -1 + 7; /* Map to offset in table */
SPrintf( TextBuffer, GStr( "\000\x18\Error: %s"), GStr( ErrorText[i]) );
PsMsg->pm_Tell( TextBuffer);
cont = FALSE;
loop = FALSE;
}
}
/* Message from progress-bar? - note: we're paused! */
if ( loop && (signal & sigWd) )
{
id = PsMsg->pm_PullPBarEvent( PB); /* Get id of gadget clicked */
if (id == 2) /* awake? */
{
PIO->IoStd.io_Flags = IOF_QUICK;
PIO->IoStd.io_Command = CMD_START; /* Continue dump (i.e. tell device we're */
DoIO( (struct IORequest *) PIO); /* going to re-use it */
/* Re-do for graphic dump */
PIO->IoDpRP.io_Command = PRD_DUMPRPORT;
PIO->IoDpRP.io_Flags = flag;
PIO->IoDpRP.io_RastPort = FakeRP;
PIO->IoDpRP.io_ColorMap = CM;
PIO->IoDpRP.io_Modes = ModeID;
PIO->IoDpRP.io_SrcX = 0;
PIO->IoDpRP.io_SrcY = 0;
PIO->IoDpRP.io_SrcWidth = PsMsg->pm_RightMargin * PsMsg->pm_CharSpace[ (UBYTE) 32];
PIO->IoDpRP.io_SrcHeight = PsMsg->pm_Font->tf_YSize + 1;
PIO->IoDpRP.io_Special = spec;
PIO->IoDpRP.io_DestCols = DestHDots;
PIO->IoDpRP.io_DestRows = DestVDots;
loop = FALSE;
}
else
{
if (id == 1) /* Shame on user, firstly paused now abandoned... */
{
AbortIO( (struct IORequest *) PIO);
WaitIO( (struct IORequest *) PIO);
PsMsg->pm_Tell( GStr ("\000\x17Printing abandoned by user!") );
cont = FALSE;
loop = FALSE;
}
}
}
}
}
else
{
/* User said stop and quit? */
if (id == 1)
{
AbortIO( (struct IORequest *) PIO);
WaitIO( (struct IORequest *) PIO);
PsMsg->pm_Tell( GStr ("\000\x17Printing abandoned by user!") );
cont = FALSE;
}
}
}
} /* End progress-bar message */
/* Firstly, clear the complete bit-plane(s) */
SetDrMd( FakeRP, JAM2); /* We want to overwrite */
SetAPen( FakeRP, 0); /* Background pen */
RectFill( FakeRP, 0, 0, FakeBM->BytesPerRow * 8 - 1, FakeBM->Rows - 1);
/* Set render pen - to make the characters visible */
SetAPen( FakeRP, 1); /* Foreground pen */
}
return cont;
}
/* ----------------------------------------------------
Try to dump the specified characters to the printer
Called with the widest string length in pixels.
NOTE:
The 'FakeBM->Depth' must have already been set to the required depth -
in this example it was set to one (monochrome).
*/
void DoTheDump( unsigned int mustHave)
{
unsigned int i, a, r, p;
unsigned char *curr, *end;
a = mustHave / PsMsg->pm_CharSpace[ (UBYTE) ' '];
if (PsMsg->pm_RightMargin < a)
i = PsMsg->pm_CaseTell( GStr( "\001\002Sure to continue with printout\n"\
"although not all characters fit onto concerned page?\n"\
"(Some beyond right margin - non-printable!)\n\n"\
"Continue?") );
if (i)
{
/* Compute size in bytes for bit-plane allocation */
i = PsMsg->pm_RightMargin * PsMsg->pm_CharSpace[ (UBYTE) 32]; /* Size in pixels */
i = (i + 15) & -16; /* 16-bit boundary */
i /= 8; /* ...in bytes */
FakeBM->BytesPerRow = i; /* Amount of rows */
FakeBM->Rows = PsMsg->pm_Font->tf_YSize + 1;
if (GfxBase->LibNode.lib_Version <= 38 \
|| (GetBitMapAttr( PsMsg->pm_EdWindow->WScreen->RastPort.BitMap, BMA_FLAGS) & BMF_STANDARD))
{
/* Standard (PLANAR) display - so the bitplanes must reside in CHIP-RAM -
for the rendering functions
*/
FakeBM->Planes[0] = (PLANEPTR) AllocMem( FakeBM->BytesPerRow * FakeBM->Rows * FakeBM->Depth, \
MEMF_CLEAR|MEMF_CHIP)
}
else
{
/* There is a non-standard Bitmap - so I guess rendering to FAST-RAM will work! */
FakeBM->Planes[0] = (PLANEPTR) AllocMem( FakeBM->BytesPerRow * FakeBM->Rows * FakeBM->Depth, MEMF_CLEAR);
}
/* Bitplane(s) allocated? */
if ( FakeBM->Planes[0])
{
/* If the Bitmap has got more than 1 Bitplane the construct below will
compute the other Bitplane addresses and stores them into the Bitmap
*/
a = (unsigned int) FakeBM->Planes[0]; /* Address allocated memory, bitplane[0] already set! */
for (i = 1; i < FakeBM->Depth; i++) /* Do it for the others (?) */
{
a += FakeBM->BytesPerRow * FakeBM->Rows; /* Plus size of one, single bitplane */
FakeBM->Planes[i] = (PLANEPTR) a; /* Store computed address */
}
/* Figure out if user wishes only to dump the marked area */
if (PsMsg->pm_BlockStart)
{
curr = PsMsg->pm_BlockStart;
end = PsMsg->pm_BlockEnd;
}
else /* No marked area, so take whole archive */
{
curr = PsMsg->pm_TextStart;
end = PsMsg->pm_TextEnd;
}
/* How many lines are in the archive/text block ? */
a = 1;
while (curr < end && *curr != 0)
if (*curr++ == 10) /* Count linefeeds */
a++;
Lines2Dump = a; /* Remember for later */
/* How many lines can be displayed per printer page? */
i = PD->pd_Preferences.PaperLength; /* Lines per page */
/* How many lines can be displayed per inch */
if (PD->pd_Preferences.PrintSpacing)
r = 8
else
r = 6;
/* How many dots can be printed out to one page in vertical direction? */
i = i * PED->ped_YDotsInch / r; /* e.g. 66 lines * 180 dpi / 6 lines per page */
/* How many pages required to print out those lines? */
p = a * PIO->IoDpRP.io_DestRows / i;
if (!p)
p = 1; /* At least one page! */
/* Check if there is a rest of lines that need an extra page,
e.g. 60 lines per page , 153 lines to print but only 2 pages computed!
*/
if (a > p * i / PIO->IoDpRP.io_DestRows)
p ++;
/* Give the user the chance to abort printing... */
SPrintf( TextBuffer, GStr( "\001\003Sure to print?\n\nPrintout would require %ld pages!"), p);
p = PsMsg->pm_CaseTell( TextBuffer);
if (p)
{
/*
'i' contains vertical dots per page, e.g. 1920,
'a' contains amount lines to print
'PIO->IoDpRP.io_DestCols' contains horizontal dots for a single line to print
'PIO->IoDpRP.io_DestRows' contains vertical dots for a single line to print
*/
VDotsPage = i;
VDotsLine = PIO->IoDpRP.io_DestRows;
HDotsLine = PIO->IoDpRP.io_DestCols;
Lines = a;
CurrYdot = 0; /* Imagine we're at the top of a page */
CurrLine = 0; /* No lines printed (yet) */
CM = GetColorMap( 2); /* Monochrome - only two colours */
if (CM)
{
SetRGB4CM( CM, 0, 0xF, 0xF, 0xF); /* Background = white */
SetRGB4CM( CM, 1, 0x0, 0x0, 0x0); /* Foreground = black */
/* Establish this colour-map for dump */
PIO->IoDpRP.io_ColorMap = CM;
/* We really want to print! */
PIO->IoDpRP.io_Special &= ~SPECIAL_NOPRINT;
SetDrMd( FakeRP, JAM2); /* We want to overwrite */
SetAPen( FakeRP, 1); /* Foreground pen */
SetBPen( FakeRP, 0); /* Background pen */
PB = PsMsg->pm_CreateProgressBar( GStr( "\002\001DAC Dumper"), \
GStr( "\000\x42\Printout completed to "), \
GStr( "\000\x43Pause/Continue"), GStr( "\000\x44\Continue"), \
GStr( "\000\x45\Abandon") );
/* Continue even the progress-bar has not been attached to Dump */
if (PsMsg->pm_BlockStart)
PsMsg->pm_DumpStrings( FakeRP, &DumpCode, PsMsg->pm_BlockStart, PsMsg->pm_BlockEnd);
else
PsMsg->pm_DumpStrings( FakeRP, &DumpCode, PsMsg->pm_TextStart, PsMsg->pm_TextEnd);
if (PB)
PsMsg->pm_FreeProgressBar( PB);
/* REMOVED - since it should be clear...
PsMsg->pm_Tell( GStr( "\002\004Print-job done.") ); */
FreeColorMap( CM);
}
else
PsMsg->pm_Tell( GStr( "\000\x19\Cannot create unicoloured colour-map!") );
}
FreeMem( FakeBM->Planes[0], FakeBM->BytesPerRow * FakeBM->Rows * FakeBM->Depth);
}
else
PsMsg->pm_Tell( GStr( "\000\x1AUnable to get RAM for printout!") );
}
else
PsMsg->pm_Tell( GStr( "\000\x1BPrint-job aborted...") );
}
/* ###############################################################
Here we go...
*/
void main( void)
{
struct ViewPort *vp;
int a, i, p, l;
/* Discover if we have been launched by Workbench */
if ( !WBenchMsg)
return;
/* Either from Workbench or BareED */
if ( strcmp( WBenchMsg->sm_Message.mn_Node.ln_Name, "BAREED") != NULL)
return;
/* Was BareED, so convert pointer to the message */
PsMsg = (struct PseudoMsg *) WBenchMsg;
GfxBase = PsMsg->pm_GfxBase;
IntuitionBase = (struct IntuitionBase *) PsMsg->pm_IntuitionBase;
LocaleBase = PsMsg->pm_LocaleBase;
GadToolsBase = PsMsg->pm_GadToolsBase;
OpenTheCatalog();
TextBuffer = (STRPTR) AllocMem( TEXTBUFFERSIZE, MEMF_CLEAR);
FakeRP = (struct RastPort *) AllocMem( sizeof( struct RastPort), MEMF_CLEAR);
FakeBM = (struct BitMap *) AllocMem( sizeof( struct BitMap), MEMF_CLEAR);
if (TextBuffer && FakeRP && FakeBM)
{
/* Create non-public message port */
if ( (PrinterPort = CreateMsgPort()) )
{
/* Allocate PrinterIO - for easier access as union */
if ( (PIO = (union PrinterIO *) CreateExtIO( PrinterPort, sizeof( union PrinterIO))) )
{
/* Open the printer.device */
if ( !(OpenDevice( "printer.device", 0, (struct IORequest *) PIO, 0)) )
{
PD = (struct PrinterData *) PIO->IoDpRP.io_Device;
PED = (struct PrinterExtendedData *) &PD->pd_SegmentData->ps_PED;
vp = &(PsMsg->pm_EdWindow->WScreen->ViewPort);
/* Get the mode-id to compute correct aspect ratio */
if ( (ModeID = GetVPModeID( vp)) != INVALID_ID)
{
/* Create a faked Raster Port so that a BAD DIMENSION error is nearly impossible!
To do this:
Tell the "printer.device" that the faked Bitmap is in horizontal direction
ten times larger than screen's! Could also be done with a fixed-width size,
e. g. 16000.
Since no rendering is performed, we can play with empty bitplanes!
*/
/* Duplicate Raster Port - a bad hack? */
CopyMem( PsMsg->pm_EdWindow->RPort, FakeRP, sizeof( struct RastPort));
FakeRP->Layer = 0;
FakeRP->BitMap = FakeBM;
FakeBM->BytesPerRow = PsMsg->pm_EdWindow->WScreen->Width * 10 / 8;
FakeBM->Rows = PsMsg->pm_EdWindow->WScreen->Height;
FakeBM->Depth = 1;
/* Fill in parts of the IODRPRequest - used to compute correct aspect ratio */
PIO->IoDpRP.io_Command = PRD_DUMPRPORT;
PIO->IoDpRP.io_RastPort = FakeRP;
PIO->IoDpRP.io_ColorMap = vp->ColorMap;
PIO->IoDpRP.io_Modes = ModeID;
PIO->IoDpRP.io_SrcX = 0;
PIO->IoDpRP.io_SrcY = 0;
/* We need a valid right margin to compute and lay out strings! */
while (PsMsg->pm_RightMargin == NULL)
PsMsg->pm_RightMargin = PsMsg->pm_RequestNumber( 0, GStr( "\002\001DAC Dumper"),\
GStr( "\002\002Enter right margin!"),\
GStr( "\002\003Okay"), 0);
/* How long is a line in pixels? */
PIO->IoDpRP.io_SrcWidth = PsMsg->pm_RightMargin * PsMsg->pm_CharSpace[ (UBYTE) 32];
/* How high is the font (plus one because BareED reserves between each text line a row! */
PIO->IoDpRP.io_SrcHeight = PsMsg->pm_Font->tf_YSize + 1;
/* We don't want to print, but we want to know the correct dimension */
PIO->IoDpRP.io_Special = SPECIAL_ASPECT|SPECIAL_NOFORMFEED|SPECIAL_TRUSTME|SPECIAL_NOPRINT;
/* Initialise with zero so "printer device" calculates dump dimension! */
PIO->IoDpRP.io_DestCols = 0;
PIO->IoDpRP.io_DestRows = 0;
/* Ask for dimension */
DoIO( (struct IORequest *) PIO);
if (PIO->IoDpRP.io_Error == 0)
{
DestHDots = p = PIO->IoDpRP.io_DestCols; /* Dots in horizontal direction
(to fit line fulfilled onto paper) */
DestVDots = l = PIO->IoDpRP.io_DestRows; /* Dots in vertical direction (height of
one single line!) */
}
else
{
a = PIO->IoDpRP.io_Error;
if (a < 0)
a = a * -1 + 7;
SPrintf( TextBuffer, GStr( "\000\x18\Error: %s"), GStr( ErrorText[a]));
PsMsg->pm_Tell( TextBuffer);
}
/* Do not continue upon error */
if ( !PIO->IoDpRP.io_Error)
{
/* How wide is a string basing on RightMargin (in pixels -
as limit for WidestStrLen()) ?
*/
a = PsMsg->pm_RightMargin * PsMsg->pm_CharSpace[ (UBYTE) 32];
/* Get the height of the font and care about the row that BareED reserves
between each text line
*/
i = PsMsg->pm_Font->tf_YSize + 1;
SPrintf( TextBuffer, GStr( "\000\x40\Dimension when using a right margin of %ld" \
" characters:\n\nline length = %4ld pixles = X-dots = %4ld\n" \
"line height = %4ld pixels = Y-dots = %4ld"), \
PsMsg->pm_RightMargin, a, p, i, l);
PsMsg->pm_Tell( TextBuffer);
/* Invoke function WidestStrLen() with a set CallBack-Hook */
if (PsMsg->pm_BlockStart)
p = PsMsg->pm_WidestStrLen( PsMsg->pm_BlockStart, PsMsg->pm_BlockEnd,\
&InformCode, a);
else
p = PsMsg->pm_WidestStrLen( PsMsg->pm_TextStart, PsMsg->pm_TextEnd,\
&InformCode, a);
/* Did the user abandoned computing? */
if (Continue)
{
/* No... */
l = p / PsMsg->pm_CharSpace[ (UBYTE) 32];
if ( l * PsMsg->pm_CharSpace[ (UBYTE) 32] < p) /* Correct number of chars! */
l ++;
SPrintf( TextBuffer, GStr( "\000\x41Widest line: %ld pixels or %ld characters!"), p, l);
PsMsg->pm_Tell( TextBuffer);
/* Now, compute X-offset for printout. Take "Printer-Prefs" left margin - not
"PrinterGfx-Prefs" settings!
*/
i = PD->pd_Preferences.PrintXOffset; /* Remember to restore later */
l = PD->pd_Preferences.PrintSpacing >> 10; /* Get used printer's font */
if (l == 0)
l = 10; /* Pica 10 cpi */
if (l == 1)
l = 12; /* Elite 12 cpi */
if (l == 2)
l = 17; /* Fine 15/17 cpi */
/* E. g.: 30 (left margin) * 10 / 10 (Pica = 10 cpi) = 30(/10ths inch) */
PD->pd_Preferences.PrintXOffset = PD->pd_Preferences.PrintLeftMargin * 10 / l;
/* Print out graphic */
DoTheDump( p);
PD->pd_Preferences.PrintXOffset = i;
}
}
}
else
PsMsg->pm_Tell( GStr( "\000\x1CInvalid screen-mode-ID") );
CloseDevice( (struct IORequest *) PIO);
}
else
PsMsg->pm_Tell( GStr( "\000\x1D\Cannot open the \"printer device\"") );
DeleteExtIO( (struct IORequest *) PIO);
}
else
PsMsg->pm_Tell( GStr( "\000\x1E\Cannot create required I/O-request") );
DeleteMsgPort( PrinterPort);
}
else
PsMsg->pm_Tell( GStr( "\000\x1F\Cannot create a message port") );
}
if (FakeBM)
FreeMem( FakeBM, sizeof( struct BitMap));
if (FakeRP)
FreeMem( FakeRP, sizeof( struct RastPort));
if (TextBuffer)
FreeMem( TextBuffer, TEXTBUFFERSIZE);
CloseTheCatalog();
}
/*
This is the end of DAC-Dump - if you can do better than me - feel free to modify.
*/